package com.ggb.reactive.controller.user

import com.fasterxml.jackson.databind.ObjectMapper
import com.ggb.reactive.domain.dto.UserLoginDTO
import com.ggb.reactive.domain.entity.User
import com.ggb.reactive.domain.vo.UserLoginVO
import com.ggb.reactive.extension.log
import com.ggb.reactive.properties.WeChatProperties
import com.ggb.reactive.repository.UserRepository
import com.ggb.reactive.service.JwtSigner
import com.ggb.reactive.utils.HttpClientUtil
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import lombok.RequiredArgsConstructor
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Mono
import java.time.Instant
import com.ggb.reactive.model.Result


@RestController
@RequestMapping("/user/user")
@Tag(name = "用户管理")
@RequiredArgsConstructor
class UserController(
    private val weChatProperties: WeChatProperties,
    private val userRepository: UserRepository,
    private val jwtSigner: JwtSigner
) {

    companion object {
        const val WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session"
    }



    @PostMapping("/login")
    @Operation(summary = "微信登录")
    fun login(@RequestBody @Validated userLoginDTO: UserLoginDTO): Mono<Result<UserLoginVO>> {
        log.info("微信登录，{}", userLoginDTO)
        return getOpenId(userLoginDTO.code).flatMap { openId ->
            log.info("getOpenId，{}", openId)
            userRepository.findByOpenid(openId)
                .flatMap { user ->
                    // 如果找到了用户，就直接使用这个用户
                    log.info("Found existing user: {}", user)
                    Mono.just(user)
                }
                .switchIfEmpty(
                    // 如果没有找到用户，就创建一个新的用户并保存
                    Mono.defer {
                        log.info("No existing user found with openid: {}, creating new user", openId)
                        userRepository.save(
                            User(
                                openid = openId,
                                createTime = Instant.now()
                            )
                        )
                    }
                )
                .map { user ->
                    // 处理用户信息，返回登录结果
                    log.info("Processing user: {}", user)


                    Result.success(
                        UserLoginVO(
                            id = user.id!!,
                            openid = user.openid!!,
                            token = jwtSigner.generateToken(user.id!!)
                        )
                    )
                }
        }
    }

    // 获取openId
    fun getOpenId(code: String): Mono<String> {
        val params = mapOf(
            "appid" to weChatProperties.appid!!,
            "secret" to weChatProperties.secret!!,
            "js_code" to code,
            "grant_type" to "authorization_code"
        )

        return HttpClientUtil.doGet(WX_LOGIN, params)
            .map { json ->
                // 此处假设使用的是Jackson等库进行JSON解析
                //val node = ObjectMapper().readTree(json)
                //val node = objectMapper.readTree(json) // 使用注入的 ObjectMapper 解析 JSON
                //node.get("openid").asText()
                try {
                    val node = ObjectMapper().readTree(json)
                    node.get("openid").asText()
                } catch (e: Exception) {
                    log.error("Error parsing JSON: {}", e.message)
                    throw RuntimeException("Error parsing JSON", e)
                }
            }
    }
}